#include <iostream>
#include "CHealerWeapon.h"
#include "CGameApp.h"
#include <cmath>
using namespace std;

extern float VIEW_WIDTH;
extern float VIEW_HEIGHT;

CHealerWeapon::CHealerWeapon()
:CWeapon( 20, 1 )
{
	RateOfFire = 4.0f;
	SpreadAngle = 15.0f;
	BulletLifeSpan = 1.5f;
	SetType( "CHealerWeapon" );
}

CHealerWeapon::CHealerWeapon( int numbullets, int spread )
:CWeapon( numbullets, spread )
{
	RateOfFire = 2.0f;
	SpreadAngle = 15.0f;
	BulletLifeSpan = 0.3f;
	SetType( "CHealerWeapon" );
}

CHealerWeapon::~CHealerWeapon()
{

}

void CHealerWeapon::Render()
{
	CWeapon::Render();
}

void CHealerWeapon::Update()
{
	//cout << "update called in bounceweapon" << endl;
	FireTimer += Ship->pParent->DeltaTime;

	//pointer to the player ship
	//CPlayer* player = Ship->pParent->Player;
	//for( int w = 0; w < Ship->pParent->NumPlayers; w++ )
	//{
	//	CPlayer* player = Ship->pParent->Player[w];

		for( int x = 0; x < NumBullets; x++ )
		{
			for( int y = 0; y < Spread; y++ )
			{
				//this should just call bullet->update()
				Bullets[x][y]->Update();

				//this bullet behavior is weapon dependant. put in weapon class
				if( Bullets[x][y]->GetAlive() ) //if( Bullets[x][y]->GetAlive() == false ) { continue; }
				{
					Bullets[x][y]->SetOldPos( Bullets[x][y]->GetPosX(), Bullets[x][y]->GetPosY() );

					//update bullet positions
					Bullets[x][y]->MovePosY( Ship->pParent->DeltaTime * Bullets[x][y]->GetSpeed() * Bullets[x][y]->GetVelY() ); 
					Bullets[x][y]->MovePosX( Ship->pParent->DeltaTime * Bullets[x][y]->GetSpeed() * Bullets[x][y]->GetVelX() );

		for( int i=0; i < Ship->pParent->NumBlocks; i++ )
		{
			float minx = Ship->pParent->Block[i]->GetPosX() - Ship->pParent->Block[i]->GetRadius();
			float maxx = Ship->pParent->Block[i]->GetPosX() + Ship->pParent->Block[i]->GetRadius();
			float miny = Ship->pParent->Block[i]->GetPosY() - Ship->pParent->Block[i]->GetRadius();
			float maxy = Ship->pParent->Block[i]->GetPosY() + Ship->pParent->Block[i]->GetRadius();


			//for( int x = 0; x < Player->PrimaryWeapon->NumBullets; x++ )
			//{
			//	for( int y = 0; y < Player->PrimaryWeapon->Spread; y++ )
			//	{
					CEntity* bullet = Bullets[x][y];
					if( bullet->GetAlive() == false ) { continue; }
					float cr    = bullet->GetCollisionRadius();
					float bminx = bullet->GetPosX() - cr;
					float bmaxx = bullet->GetPosX() + cr;
					float bminy = bullet->GetPosY() - cr;
					float bmaxy = bullet->GetPosY() + cr;
					if( bminx > maxx ) { continue; } //bullet to the right, no collision
					if( bmaxx < minx ) { continue; } //bullet to the left, no collision
					if( bminy > maxy ) { continue; } //bullet above, no collision
					if( bmaxy < miny ) { continue; } //bullet below, no collision
					//collision, do something
					bullet->Kill();
					//if there's a collision along the x-axis, reverse the y
					//if( bullet->GetOldPosX()-cr < maxx && bullet->GetOldPosX()+cr > minx )
					//{
					//	//column collision, reverse the y
					//	if( bullet->GetOldPosY() < bullet->GetPosY() )//moving up
					//	{
					//		bullet->SetPosY( miny-cr );
					//		bullet->SetVel( bullet->GetVelX(), bullet->GetVelY()*-1 );
					//		if( bullet->GetVelX() < 0 )		{ bullet->SetFaceAngle( (atan( bullet->GetVelY()/bullet->GetVelX() )*57.2958f)+180 ); }
					//		if( bullet->GetVelX() >= 0 )	{ bullet->SetFaceAngle( atan( bullet->GetVelY()/bullet->GetVelX() )*57.2958f ); }
					//		continue;
					//	}
					//	if(bullet->GetOldPosY() > bullet->GetPosY() )//moving down
					//	{
					//		bullet->SetPosY( maxy+cr );
					//		bullet->SetVel( bullet->GetVelX(), bullet->GetVelY()*-1 );
					//		if( bullet->GetVelX() < 0 )		{ bullet->SetFaceAngle( (atan( bullet->GetVelY()/bullet->GetVelX() )*57.2958f)+180 ); }
					//		if( bullet->GetVelX() >= 0 )	{ bullet->SetFaceAngle( atan( bullet->GetVelY()/bullet->GetVelX() )*57.2958f ); }
					//		continue;
					//	}
					//}
					//else
					//{
					//	if( bullet->GetOldPosY()-cr < maxy && bullet->GetOldPosY()+cr > miny )
					//	{
					//		//row collision, reverse the x
					//		if( bullet->GetOldPosX() < bullet->GetPosX() )//moving right
					//		{
					//			bullet->SetPosX( minx-cr );
					//			bullet->SetVel( bullet->GetVelX()*-1, bullet->GetVelY() );
					//			if( bullet->GetVelX() < 0 )		{ bullet->SetFaceAngle( (atan( bullet->GetVelY()/bullet->GetVelX() )*57.2958f)+180 ); }
					//			if( bullet->GetVelX() >= 0 )	{ bullet->SetFaceAngle( atan( bullet->GetVelY()/bullet->GetVelX() )*57.2958f ); }
					//			continue;
					//		}
					//		else
					//		{
					//			if(bullet->GetOldPosX() > bullet->GetPosX() )//moving left
					//			{
					//				bullet->SetPosX( maxx+cr );
					//				bullet->SetVel( bullet->GetVelX()*-1, bullet->GetVelY() );
					//				if( bullet->GetVelX() < 0 )		{ bullet->SetFaceAngle( (atan( bullet->GetVelY()/bullet->GetVelX() )*57.2958f)+180 ); }
					//				if( bullet->GetVelX() >= 0 )	{ bullet->SetFaceAngle( atan( bullet->GetVelY()/bullet->GetVelX() )*57.2958f ); }
					//			}
					//		}
					//	}
					//}
		}//next block
	#if 1
		//check for polygon collisions
	for( int j = 0; j < Ship->pParent->NumPolygons; j++ )
	{
		CPolygon* poly = &Ship->pParent->Polygons[j];//PolyBlock;
		CEntity* bullet = Bullets[x][y];
		if( poly->InBoundingBox( bullet ) == false ) { continue; }
		Vector2d prev,curr;
		//loop through each line of the polygon and check for collision with the bullet
		for( int i = 0; i < poly->NumVectors + 1; i++ )
		{
			//store the current vector
			curr = poly->Polygon[i% poly->NumVectors];
			if( i==0 ) { prev = curr; continue; }
			//got my line, time to test it against the bullet
			Vector2d vec = Vector2d( curr.x - prev.x , curr.y - prev.y );

			//vec is the vector of the line, norm is the normalized normal of vec
			//need to test line collision between vec and the bullet
			Vector2d bvec = Vector2d( bullet->GetPosX() - bullet->GetOldPosX() , bullet->GetPosY() - bullet->GetOldPosY() );
			Vector2d bstart = bullet->OldPos;
			Vector2d bend	= bullet->Pos;
			//bstart bend is the bullet start and end point, bvec is the line from the old bullet pos to the current pos
			//prev and curr is the line start and end point, vec is the line from one point on the polygon to another, clockwise
			//norm is the normal of vec, facing away from the polygon

			float f = ( vec.y * bvec.x ) - ( vec.x * bvec.y );
			Vector2d c = Vector2d( bend.x - curr.x , bend.y - curr.y ); // end points of the bullet and line
			float aa = ( vec.y * c.x ) - ( vec.x * c.y );
			float bb = ( bvec.y * c.x ) - ( bvec.x * c.y );

			bool s = true;
			if(f <= 0)
			{
				if(aa > 0 || bb > 0 || aa < f || bb < f )   { s = false; }
				//if(bb > 0)    { s = false; }
				//if(aa < f)    { s = false; }
				//if(bb < f)    { s = false; }
			}
			if( f > 0 )
			{
				if(aa < 0 || bb < 0 || aa > f || bb > f )   { s = false; }
				//if(aa < 0 )   { s = false; }
				//if(bb < 0)    { s = false; }
				//if(aa > f)    { s = false; }
				//if(bb > f)     { s = false; }
			}
			
			if( s == true )
			{
				float contact = 1.0f - (aa/f);
				bullet->Pos.x = ((bvec.x) * contact) + bstart.x;
				bullet->Pos.y = ((bvec.y) * contact) + bstart.y;
				Vector2d norm = Vector2d( vec.y*-1, vec.x );
				//normalize it
				float length = sqrtf( norm.x * norm.x + norm.y * norm.y );
				norm.x /= length;
				norm.y /= length;
				//cout << vec.x << " " << vec.y << " " << i << norm.x << " " << norm.y << endl;

				//cout << norm.x << " " << norm.y << " " << bvec.x << " " << bvec.y << endl;
				Vector2d u = Vector2d( 1*norm.x * (bvec.x * norm.x + bvec.y * norm.y) , 1*norm.y * (bvec.x * norm.x + bvec.y * norm.y) );
				Vector2d w = Vector2d( bvec.x - u.x, bvec.y - u.y );
				Vector2d newvec = Vector2d( w.x - u.x , w.y - u.y );
				//newvec.x *= 100;
				//newvec.y *= 100;
				length = sqrtf( newvec.x * newvec.x + newvec.y * newvec.y );
				newvec.x /= length;
				newvec.y /= length;
			// bool only = true;
			//if( only == true )
			//{
			//	cout << "bullet direction     " << bvec.x << " " << bvec.y << endl;
			//	cout << "line normal          " << norm.x << " " << norm.y << endl;
			//	cout << "new bullet direction " << newvec.x << " " << newvec.y << endl;
			//	only = false;
			//}
				//cout << newvec.x << " " << newvec.y << endl;
				//bullet->SetFaceAngle( newvec.x, newvec.y );
				if( newvec.x < 0 )		{ bullet->m_fFaceAngle = ( (atan( newvec.y/newvec.x )*57.2958f)+180 ); }
				if( newvec.x >= 0 )		{ bullet->m_fFaceAngle = ( atan( newvec.y/newvec.x )*57.2958f ); }
				bullet->SetVel( newvec.x, newvec.y ); //norm.x, norm.y );
				bullet->MovePosX( norm.x * 0.01f );
				bullet->MovePosY( norm.y * 0.01f );
				//v is the bullet velocity vector
				//w is parallel to the wall
				//u is perpindicular to it
				//n is the normal
				//v2 is the new velocity vector for the bullet


				//bullet->Kill();
			}
			//bullet->GetPos = bullet->G->Get*out = 1.0 - (aa / f);
			//Point intersection = ((B2 - B1) * out) + B1;

			//bstart + bvec*t

			prev = curr;
		}
	}//next polygon
	#endif
		//if collision is found, find out where
		//calculate new velocity vector and position


					//check out of bounds
					float edge = Ship->pParent->WorldEdge;

					if( Bullets[x][y]->GetPosY() > edge )//VIEW_HEIGHT * 0.5f )	
					{
						Bullets[x][y]->SetPosY( edge );//VIEW_HEIGHT * 0.5f );
						Bullets[x][y]->SetVel( Bullets[x][y]->GetVelX(), Bullets[x][y]->GetVelY()*-1 );
						if( Bullets[x][y]->GetVelX() < 0 )	{ Bullets[x][y]->SetFaceAngle( (atan( Bullets[x][y]->GetVelY()/Bullets[x][y]->GetVelX() )*57.2958f)+180 ); }
						if( Bullets[x][y]->GetVelX() >= 0 )	{ Bullets[x][y]->SetFaceAngle( atan( Bullets[x][y]->GetVelY()/Bullets[x][y]->GetVelX() )*57.2958f ); }
						//Bullets[x][y]->TakeDamage(); 
						continue;
					}
					if( Bullets[x][y]->GetPosY() < -edge )//VIEW_HEIGHT *-0.5f )	
					{
						Bullets[x][y]->SetPosY( -edge );//VIEW_HEIGHT * -0.5f );
						Bullets[x][y]->SetVel( Bullets[x][y]->GetVelX(), Bullets[x][y]->GetVelY()*-1 );
						if( Bullets[x][y]->GetVelX() < 0 )	{ Bullets[x][y]->SetFaceAngle( (atan( Bullets[x][y]->GetVelY()/Bullets[x][y]->GetVelX() )*57.2958f)+180 ); }
						if( Bullets[x][y]->GetVelX() >= 0 )	{ Bullets[x][y]->SetFaceAngle( atan( Bullets[x][y]->GetVelY()/Bullets[x][y]->GetVelX() )*57.2958f ); }
						//Bullets[x][y]->TakeDamage();
						continue;
					}
					if( Bullets[x][y]->GetPosX() > edge )//VIEW_WIDTH  * 0.5f )
					{ 
						Bullets[x][y]->SetPosX( edge );//VIEW_WIDTH * 0.5f );
						Bullets[x][y]->SetVel( Bullets[x][y]->GetVelX()*-1, Bullets[x][y]->GetVelY() );
						if( Bullets[x][y]->GetVelX() < 0 )	{ Bullets[x][y]->SetFaceAngle( (atan( Bullets[x][y]->GetVelY()/Bullets[x][y]->GetVelX() )*57.2958f)+180 ); }
						if( Bullets[x][y]->GetVelX() >= 0 )	{ Bullets[x][y]->SetFaceAngle( atan( Bullets[x][y]->GetVelY()/Bullets[x][y]->GetVelX() )*57.2958f ); }
						//Bullets[x][y]->TakeDamage(); 
						continue;
					}
					if( Bullets[x][y]->GetPosX() < -edge )//VIEW_WIDTH  *-0.5f )	
					{
						Bullets[x][y]->SetPosX( -edge );//VIEW_WIDTH * -0.5f );
						Bullets[x][y]->SetVel( Bullets[x][y]->GetVelX()*-1, Bullets[x][y]->GetVelY() );
						if( Bullets[x][y]->GetVelX() < 0 )	{ Bullets[x][y]->SetFaceAngle( (atan( Bullets[x][y]->GetVelY()/Bullets[x][y]->GetVelX() )*57.2958f)+180 ); }
						if( Bullets[x][y]->GetVelX() >= 0 )	{ Bullets[x][y]->SetFaceAngle( atan( Bullets[x][y]->GetVelY()/Bullets[x][y]->GetVelX() )*57.2958f ); }
						//Bullets[x][y]->TakeDamage();
					}
				}
			}//next spread
		}//next bullet
	//}//next player
}

void CHealerWeapon::Load()
{
	if( Ship == NULL )	{ cout << "weapon load failed, no player attached" << endl; return; }
	SetGame( Ship->pParent );
	for( int x = 0; x < NumBullets; x++ )
	{
		for( int y = 0; y < Spread; y++ )
		{
			Bullets[x][y]->SetAlive( false );
			Bullets[x][y]->SetGame( Ship->pParent );
			Bullets[x][y]->SetHealth( 1 );
			Bullets[x][y]->SetDamage( 1 );
			Bullets[x][y]->SetFaceAngle( Ship->GetFaceAngle() );
			Bullets[x][y]->SetPos( Ship->GetPosX(), Ship->GetPosY() );
			Bullets[x][y]->SetVel( Ship->GetVelX(), Ship->GetVelY() );
			Bullets[x][y]->SetSpeed( 9.0f );
			Bullets[x][y]->SetRotateSpeed( 0.45f );
			Bullets[x][y]->SetSize( 0.8f );
			Bullets[x][y]->SetCollisionSize( 0.25f );
			Bullets[x][y]->SetLifeSpan( 7 );
			if( Ship->GetType() == "CEnemy" ) { Bullets[x][y]->SetType( "CEnemyCBounceWeapon" ); }
			else {								Bullets[x][y]->SetType( "FriendWave" ); }
			Bullets[x][y]->SetTexture( Ship->pParent->BulletTexture.texID );
			Bullets[x][y]->SetFireAnimationTexture( Ship->pParent->FireAnimationTexture );
			Bullets[x][y]->SetExplosionTexture( Ship->pParent->ExplosionTexture );
			//Bullets[x][y]->SetLifeSpan( 4.0f );
		}//next bullet in the spread
	}//next bullet
}

void CHealerWeapon::FireBullet()
{
	//if the ship is dead, the ship can't fire
	if( Ship->GetAlive() == false ) { return; }

	//if not enough time has passed, the ship can't fire
	if( FireTimer <= 1/RateOfFire ) { return; }

	bool done = false;//when done is true, a bullet is fired and no more needs to be
	bool rowcanshoot = true; //will remain true as long as every bullet in the spread can fire
	//loop through the bullets
	for( int x = 0; x < NumBullets; x++ )
	{
		if( done == true ) { break; }//bullet fired, no need to add more
		rowcanshoot = true;
		for( int y = 0; y < Spread; y++ )
		{
			if( Bullets[x][y]->GetAlive() || Bullets[x][y]->GetEAlive() )
			{
				rowcanshoot = false;
				break;
			}
		}
		if( rowcanshoot == false ) { continue; }
		for( int y = 0; y < Spread; y++ )
		{
			//if( done == true ) { continue; }//bullet fired, no need to add more
			//if( Bullets[x][y]->GetAlive() ) { continue; }//bullet active, don't reset it yet
			pParent->audio->Play("fire2");
			Bullets[x][y]->SetAlive( true );
			Bullets[x][y]->SetLifeSpan( BulletLifeSpan );
			float tempx = cos((Ship->GetFaceAngle()-90)*0.0174533f);
			float tempy = sin((Ship->GetFaceAngle()-90)*0.0174533f);
			//SetVel( cos(GetFaceAngle()*0.0174533f), sin(GetFaceAngle()*0.0174533f) );
			//set the position to the point of the gun, position plus vel scaled by radius
			//Bullets[x][y]->SetPos( Ship->GetPosX() , Ship->GetPosY() );
			Bullets[x][y]->SetPos( Ship->GetPosX() + tempx*Ship->GetCollisionRadius()*0.9f,Ship->GetPosY() + tempy*Ship->GetCollisionRadius()*0.9f );
			Bullets[x][y]->SetOldPos( Ship->GetPosX() , Ship->GetPosY() );
			//setfaceangle to adjust to spread angle
			Bullets[x][y]->SetFaceAngle( Ship->GetFaceAngle() - (((Spread - 1)*SpreadAngle)/2 ) + y * SpreadAngle-90 );
			//Bullets[x][y]->SetHealth( 1 );
			Bullets[x][y]->StartFireAnimation();
			//have to rotate the face angle, switch later to other setfaceangle
			//only this setfaceangle sets it based on direction, not a point in space
			//need to reemplement pointto
			done = true;
		}//next spread
	}//next bullet
	FireTimer = 0;
//}//endif bullet can be fired

}


